﻿package duplexpipe.sni;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import duplexpipe.utils.Verboser;

public class TCPCommunicator implements NetCommunicator
{
	private Socket socket;
	private InputStream in;
	private OutputStream out;
	private String type;

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public TCPCommunicator (Socket socket, int port,String type )
	{
		try
		{
			if (socket != null)
			{
				this.socket = socket;
				this.type = type;
				in = new BufferedInputStream ( socket.getInputStream () );
				out = new BufferedOutputStream ( socket.getOutputStream () );
			}
		}
		catch ( IOException e )
		{
			e.printStackTrace ();
		}
	}

	public TCPCommunicator ( String host, int port ,String type) throws IOException
	{
		try
		{
			this.type = type;
			socket = new Socket();
			SocketAddress address = new InetSocketAddress(host, port );
			//socket.setSoTimeout(1000 * 1);
			socket.setKeepAlive(true);
			//socket.setOOBInline(true);
			socket.connect(address,0);
			
			in = new BufferedInputStream ( socket.getInputStream () );
			out = new BufferedOutputStream ( socket.getOutputStream () );
		}
		catch ( UnknownHostException e )
		{
			Verboser.getVerboser ().bail ( e.getMessage () );
		}
		
	}

	@Override
	public void close() {
		try {
			if (out != null) {
				out.close();
			}
			if (in != null) {
				in.close();
			}
			if (socket != null) {
				try {
					socket.shutdownInput();
				} catch (IOException e) {
					// TODO: handle exception
				}
				try {
					socket.shutdownOutput();
				} catch (IOException e) {
					// TODO: handle exception
				}
				
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			try {
				socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public int read ( byte[] b, int off, int len ) throws IOException
	{
		int result = in.read ( b, off, len );
		CommonUtil.LogPrint("read from " + socket.getRemoteSocketAddress().toString());
		return result;
	}

	@Override
	public void write ( byte[] b, int off, int len ) throws IOException
	{
		out.write ( b, off, len );
		out.flush ();
		
		CommonUtil.LogPrint("write to " + socket.getRemoteSocketAddress().toString());	
	}

	@Override
	public String getType() {
		return type;
	}
}
